<?php
/////////////////////////////////////////////////////////////////
// SpeedPHP中文PHP框架, Copyright (C) 2008 - 2010 SpeedPHP.com //
/////////////////////////////////////////////////////////////////
define("SPANONYMOUS","SPANONYMOUS"); // 无权限设置的角色名称
/**
 * 基于组的用户权限判断机制
 * 要使用该权限控制程序，需要在应用程序配置中做以下配置：
 * 有限控制的情况，在配置中使用	'launch' => array( 'router_prefilter' => array( array('spAcl','mincheck'), ), )
 * 强制控制的情况，在配置中使用	'launch' => array( 'router_prefilter' => array( array('spAcl','maxcheck'), ), )
 */
class spAcl
{
	/**
	 * 默认权限检查的处理程序设置，可以是函数名或是数组（array(类名,方法)的形式）
	 */
	public $checker = array('spAclModel','check');
	
	/**
	 * 默认提示无权限提示，可以是函数名或是数组（array(类名,方法)的形式）
	 */
	public $prompt = array('spAcl','def_prompt');
	/**
	 * 构造函数，设置权限检查程序与提示程序
	 */
	public function __construct()
	{	
		$params = spExt("spAcl");
		if( !empty($params["prompt"]) )$this->prompt = $params["prompt"];
		if( !empty($params["checker"]) )$this->checker = $params["checker"];
	}
	/**
	 * 强制控制的检查程序，适用于后台。无权限控制的页面均不能进入
	 */
	public function maxcheck()
	{
		$acl_handle = $this->check();
		if( 1 !== $acl_handle ){
			$this->prompt();
			return FALSE;
		}
		return TRUE;
	}

	/**
	 * 有限的权限控制，适用于前台。仅在权限表声明禁止的页面起作用，其他无声明页面均可进入
	 */
	public function mincheck()
	{
		$acl_handle = $this->check();
		if( 0 === $acl_handle ){
			$this->prompt();
			return FALSE;
		}
		return TRUE;
	}
	
	/**
	 * 使用程序调度器进行检查等处理
	 */
	private function check()
	{
		GLOBAL $__controller, $__action;
		$checker = $this->checker; //array('spAclModel','check')
		if( is_array($checker) ){
            //返回 spClass(spAclModel)->check(控制器,动作)
			return spClass($checker[0])->{$checker[1]}($__controller, $__action);
		}else{
			return call_user_func_array($checker, array($__controller, $__action));
		}
	}
	/**
	 * 无权限提示跳转
	 */
	public function prompt()
	{
		$prompt = $this->prompt;//array('spAcl','def_prompt')
		if( is_array($prompt) ){
			return spClass($prompt[0])->{$prompt[1]}();
		}else{
			return call_user_func_array($prompt,array());
		}
	}
	
	/**
	 * 默认的无权限提示跳转
	 */
	public function def_prompt()
	{
		$url = spUrl(); // 跳转到首页，在强制权限的情况下，请将该页面设置成可以进入。
		echo "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><script>function sptips(){alert(\"Access Failed!\");location.href=\"{$url}\";}</script></head><body onload=\"sptips()\"></body></html>";
		exit;
	}  
    
}

 /**
 * ACL操作类，通过数据表确定用户权限
 * 表结构：
 * CREATE TABLE acl
 * (
 * 	aclid int NOT NULL AUTO_INCREMENT,
 * 	name VARCHAR(200) NOT NULL,
 * 	controller VARCHAR(50) NOT NULL,
 * 	action VARCHAR(50) NOT NULL,
 * 	acl_name VARCHAR(50) NOT NULL,
 * 	PRIMARY KEY (aclid)
 * ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
 */
class spAclModel extends spModel
{
	public $pk = 'aclid';
	/**
	 * 表名
	 */
	public $table = 'acl';

	/**
	 * 检查对应的权限
	 *
	 * 返回1是通过检查，0是不能通过检查（控制器及动作存在但用户标识没有记录）
	 * 返回-1是无该权限控制（即该控制器及动作不存在于权限表中）
	 * 
	 * @param gid    用户组ID
	 * @param controller    控制器名称
	 * @param action    动作名称
	 */
	public function check($controller, $action)
	{
	  //echo $gid.$controller.$action;
      //exit;
      //根据所属的组名或所属组ID，2，来获取权限aclok（3,4,5,6)
      //然后根据获取来的 控制器名称和动作名称 来获取aclid 
      //然后，判断aclid 是否存在于aclok(3,4,5,6)当中，如果存在返回1
      $gid=1;
      $utmp=$_REQUEST['utmp'];
      $stmp=$_REQUEST['stmp'];
      $userinfo=spClass('userModel')->userinfo($utmp,$stmp);
      $gid=($userinfo['gid'])?$userinfo['gid']:1;
      $aclok= spClass("usergroupModel")->getaclok($gid);  //根据组ID获取相关组的权限，默认是1，游客权限 
      $aclok=explode(',', $aclok);//将获得数据库中用户组表中的ACLOK字段的字符串转换为数组
      $rows = array('controller' => $controller, 'action' => $action ); //先通过获取到的控制器和动作进行数据库搜索
		if( $acl = $this->findAll($rows) ){//如果有数据存在那么就将所属的ID同数组$aclok进行比较，看此ID是包含在数组中
			foreach($acl as $v){
				if(in_array($v['aclid'], $aclok))return 1;//如果包含就返回1
			}
			return 0;//不包含返回0
		}else{
			return -1;//数据库中不存在此控制器或动作 返回1
		}
	}
    
    public function getacllist($uid){
        $abc=spClass("usergroupModel")->getaclok($uid);
        $str="aclid in(".$abc.")";
        return $str;
    }
    
    public function gettopList($uid){
        $str2=$this->getacllist($uid);
        $str3="menuview=0 and fid=0 and ".$str2;
		$arr = $this->spCache(3600)->findAll($str3,'sort asc',null,null);
		return $arr;
	}
    
    public function getleftList($fid,$uid){
        $str2=$this->getacllist($uid);
        $str3="menuview=1 and fid=".$fid." and ".$str2;
		$arr = $this->spCache(3600)->findAll($str3,'sort asc',null,null);
		return $arr;
	}
    
    public function findacl($aclid){
		$condition = array('aclid'=>$aclid);
		$arr = $this->find($condition);
		return $arr;
	}
}